package com.atqinke.designpattern.creationtype.singlecase;

import org.springframework.util.SerializationUtils;

import java.io.Serializable;
import java.lang.reflect.Constructor;

/**
 * @BelongsProject: BasicConnection
 * @BelongsPackage: com.atqinke.DesignPattern.creation.SingleCase
 * @Author: NieHk
 * @CreateTime: 2022-08-16  09:49
 * @Description: 使用静态内部类实现单例模式
 * @Version: 1.0
 */
public class StaticInnerClass implements Serializable {

    private static boolean flag = false;

    //声明静态内部类，在内部类中创建StaticInnerClass对象
    private static class SingletonHolder {
        private static StaticInnerClass staticInnerClass = new StaticInnerClass();
    }

    //私有构造器
    private StaticInnerClass() {
//        //解决反射问题
//        synchronized (StaticInnerClass.class){
//            if (flag){
//                throw new RuntimeException("对象已创建,不能创建多个对象");
//            }
//            flag = true;
//        }
    }

    //提供获取方法
    public static StaticInnerClass getStaticInnerClass() {
        return SingletonHolder.staticInnerClass;
    }

    /**
     * @param
     * @description: 测试方法：对其进行反序列化攻击
     * @author: NieHK
     * @date: 2022/8/16 10:03
     * @return: boolean
     */
    public static boolean serialize() {
        //获取StaticInnerClass对象
        StaticInnerClass staticInnerClass = StaticInnerClass.getStaticInnerClass();
        //对staticInnerClass序列化
        byte[] serialize = SerializationUtils.serialize(staticInnerClass);
        //通过反序列化得到newStaticInnerClass对象
        StaticInnerClass newStaticInnerClass = (StaticInnerClass) SerializationUtils.deserialize(serialize);
        //比较两对象是否相等
        return staticInnerClass == newStaticInnerClass;
    }

    /**
     * @param
     * @description: 测试方法：对其进行反射攻击
     * @author: NieHK
     * @date: 2022/8/16 10:05
     * @return: boolean
     */
    public static boolean reflex() throws Exception {
        //获取StaticInnerClass对象
        StaticInnerClass staticInnerClass = StaticInnerClass.getStaticInnerClass();

        Constructor<StaticInnerClass> constructor = StaticInnerClass.class.getDeclaredConstructor();
        constructor.setAccessible(true);
        //通过反射得到newStaticInnerClass对象
        StaticInnerClass newStaticInnerClass = constructor.newInstance();
        //比较两对象是否相等
        return staticInnerClass == newStaticInnerClass;
    }

    //当进行反序列化时，会自动调用该方法，用此方法解决序列化攻击.
    public Object readResolve(){
        return StaticInnerClass.getStaticInnerClass();
    }

    /**
     * @param args
     * @description: 测试
     * @author: NieHK
     * @date: 2022/8/16 10:10
     * @return: void
     */
    public static void main(String[] args) {
        //反序列测试
        //没有readResolve方法时，返回false。有readResolve方法时，返回true。
        System.out.println(serialize());
        try {
            //在私有化构造器中根据逻辑判断是否抛异常，能解决反射攻击


            //反射测试
            System.out.println(reflex());//false
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
